using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;

namespace Barrage.Global
{
    /// <summary>
    /// Holds a dictionary of keys and values for configuration purposes.
    /// It can load and store the config values to a xml file
    /// </summary>
    public class Config
    {
        const string XML_CONFIG_ELEMENT = "Config";
        const string XML_KEY_ATTRIBUTE = "key";
        const string XML_VALUE_ATTRIBUTE = "value";
        
        Dictionary<string,string> config;

        /// <summary>
        /// Constructor. Inits an empty config.
        /// </summary>
        public Config(){
            config=new Dictionary<string,string>();
        }
        /// <summary>
        /// Adds a new key/value pair
        /// </summary>
        /// <param name="key">Configuration key</param>
        /// <param name="value">Parameter value</param>
        public void Add(string key, string value)
        {
            config.Add(key, value);
        }

        /// <summary>
        /// Gets/Sets the value of the configuration key specified
        /// </summary>
        /// <param name="type">Configuration key</param>
        /// <returns>The configuration value or an empty string if there isn't any</returns>
        public string this[string type] { 
            get { string ret; if (this.config.TryGetValue(type,out ret)) return ret; return ""; }
            set { if (!this.config.ContainsKey(type)) Add(type, value); else this.config[type] = value; }
        }

        /// <summary>
        /// Creates an xml structure to save the configuration in an xml file
        /// </summary>
        /// <param name="document">Xml document to place the xml structure on</param>
        /// <param name="elementName">Name of the main configuration element</param>
        /// <returns>An xml structure to save the configuration in an xml file</returns>
        public XmlElement StoreConfig(XmlDocument document,string elementName)
        {
            XmlElement x = document.CreateElement(elementName);
            foreach(string s in config.Keys)
            {
                XmlElement child=document.CreateElement(XML_CONFIG_ELEMENT);
                child.SetAttribute(XML_KEY_ATTRIBUTE,s);
                child.SetAttribute(XML_VALUE_ATTRIBUTE,config[s]);
                x.AppendChild(child);
            }
            return x;
        }

        /// <summary>
        /// Constructor from a xml node list. Loads key / value pairs from the xml structure
        /// </summary>
        /// <param name="xmlNodes">xml configuration nodes</param>
        public Config(XmlNodeList xmlNodes):this()
        {
            LoadXml(xmlNodes);            
        }

        /// <summary>
        /// Tells if the specified key has a value in the configuration
        /// </summary>
        /// <param name="key">Configuration key</param>
        /// <returns>True if the specified key exists, false otherwise</returns>
        public bool Contains(string key)
        {
            return config.ContainsKey(key);
        }

        /// <summary>
        /// Loads the specified Xml node list and adds the found key/value pairs to the configuration dictionary
        /// </summary>
        /// <param name="xnl">Xml node list to check</param>
        public void LoadXml(XmlNodeList xnl)
        {
            foreach (XmlNode xn in xnl)
            {
                if (xn.Name.Equals(XML_CONFIG_ELEMENT))
                {
                    Add(XmlHelper.GetXMLAttribute(xn, XML_KEY_ATTRIBUTE), XmlHelper.GetXMLAttribute(xn, XML_VALUE_ATTRIBUTE));
                }
            }
        }

        /// <summary>
        /// Loads an xml file and returns a Config instance with config values from the root element
        /// </summary>
        /// <param name="file">file path</param>
        /// <returns>A Config instance with config values from the root element</returns>
        public static Config LoadXml(string file)
        {
            XmlDocument doc = new XmlDocument();
            doc.Load(file);
            
            return new Config(doc.ChildNodes);
        }
    }
}
